import com.jcraft.jsch.*
import com.jcraft.jcterm.*
import java.util.Map;
import java.awt.Color
import javax.swing.*
import javax.swing.tree.DefaultMutableTreeNode as TreeNode

import sun.net.ProgressSource.State;
import net.sshiffon.*
import java.awt.event.KeyEvent

class ConnectionTabController {
    // these will be injected by Griffon
    def model
    def view

    void mvcGroupInit(Map<String,?> args) {
        // this method is called after model and view are injected
    }
    /*
    void populateLocalIPAddress() {
        //model.netInterfaces.addAll(app.models.Sshiffon.netInterfaces)
        //edt { view.localIPAddress.model = new DefaultComboBoxModel(model.netInterfaces.toArray()) }
    }*/

    boolean open() {
    	return true
    }

    /** 
     * Called when the tab with this document gains focus. 
     */  
    String activate(state) {  
        // save the state object so we can update it   
        model.state = state  
        // sync the model and document state  
        model.updateState()
        if(!model.connected)
        {
        	view.user.requestFocusInWindow()
        }
        return model.mvcId
    }
   
    /** 
     * Called when the tab with this document loses focus. 
     */  
    void deactivate() {  
        // forget the state object  
        model.state = null  
    }
    
    /*
    def action = { evt = null ->
    }
    */
    public void refreshConnectionsList()
    {
    	app.models.Sshiffon.saveConnections()
        app.models.Sshiffon.loadConnections()
        refreshConnectionsView()
    }


    public void load(Object[] path)
    {
        if(path.length==3)
        {
            def group =app.models.Sshiffon.config.groups[path[1].toString()]
            def connection = app.models.Sshiffon.config.connections[path[2].toString()]
            if(connection!=null)
            {
                view.connectionName.text = path[2].toString()
                model.currentSetting.fromMap(connection)

                model.tunnels.clear()
                def tunnels = connection.tunnels ? connection.tunnels : []
                model.tunnels.addAll(tunnels)
                view.group.setSelectedItem(path[1].toString())
                view.reloadTunnels()
            } else {
            	logger.warn("Warning: no connection data for ${path}");
            }
        }
    }

    public void renameTab(title, icon, toolTipText)
    {
    	int idx = app.views.Sshiffon.mainTabbedPane.getSelectedIndex()
    	app.views.Sshiffon.mainTabbedPane.setTitleAt(idx, title)
    	app.views.Sshiffon.mainTabbedPane.setIconAt(idx,icon)
    	app.views.Sshiffon.mainTabbedPane.setToolTipTextAt(idx,toolTipText)
    }

    public void showConnect(String group, String savedName)
    {
          logger.info("Attempting connection to ${model.currentSetting.user}@${model.currentSetting.host}:${model.currentSetting.port}")
          if(savedName && group)
          {
          	//save item?W
          }
          def settings= model.currentSetting.toMap()
          ConnectionSetting connSetting= new ConnectionSetting(model.currentSetting.toMap())
          
          def mvcId=  "${model.mvcId}_connected"
          model.connectedGroup = buildMVCGroup('Connected',
              mvcId,
              tabs: model.tabs,
              tabId : model.mvcId,
              mvcId : mvcId,
              settings: connSetting,
              //connectionConfigGroup: [controller: this, model: model, view: view],
              group : group,
              state : model.state,
              savedName : savedName
           			  )
          def title = savedName ? "${savedName}  " : "${connSetting.user}@${connSetting.host}  "
          def icon = view.imageIcon('/crystal16/multiple_monitors.png')
          def toolTip= "${connSetting.user}@${connSetting.host}"
          renameTab(title,icon,toolTip)
          
          //add CardLayout to the rootPanel
          view.splitPane.visible=false
          view.rootPanel.remove(view.splitPane)
          model.connectedGroup.view.mainPanel.layout.show( model.connectedGroup.view.mainPanel, 'connectingCard' )
          model.connectedGroup.view.mainPanel.add(view.connectionConfigPanel,'configCard')
          view.rootPanel.add(model.connectedGroup.view.rootPanel, 'grow')
  	      if (model.connectedGroup.controller.open()) 
  	      {
  	    	  model.readyToConnect=false
  	          model.updateState(model.currentSetting.initialView)
  	    	  model.connected=true  //connected stays false until after updating state
	  	      view.clearAction.enabled= false
  	      } else {
  	          destroyMVCGroup(mvcId)
  	      }
    }



    void refreshConnectionsView()
    {
        view.savedConnections.model.root.removeAllChildren()
        def groups = []
        app.models.Sshiffon.savedConnections.each { groupname,group ->
            //logger.trace("adding ${groupname} to tree")
            TreeNode node = new TreeNode(groupname)
            group.each { conn ->
                def connNode= new TreeNode(conn)
                node.add(connNode)
            }
            view.savedConnections.model.root.add(node)
            groups.add(groupname)
        }
        view.savedConnections.model.reload(view.savedConnections.model.root)
        for (int i = 0; i < view.savedConnections.getRowCount(); i++) {
            view.savedConnections.expandRow(i);
        }

        //groups dropdown
        def item = view.group.getSelectedItem()
        view.group.model = new DefaultComboBoxModel(groups.toArray())
        if(groups.contains(item)) view.group.setSelectedItem(item)
        
    }

    void addTunnel(String localPort, String remoteHost, String remotePort)
    {
    	//add to model
    	model.tunnels.add([localPort:localPort,remoteHost:remoteHost,remotePort:remotePort,enabled:true])

    	//sync model to view
	    view.reloadTunnels()
    	
    	//if connected, sync model to actual connection
	    if(model.connected) {
    		model.connectedGroup.controller.tunnel(localPort, remoteHost, remotePort)
    	}
    }

    void toggleTunnel(i)
    {
    	model.tunnels[i].enabled = !model.tunnels[i].enabled
    	if(model.connected)
    	{
    		if(model.tunnels[i].enabled)
    		{
    			model.connectedGroup.controller.tunnel(model.tunnels[i].localPort,model.tunnels[i].remoteHost, model.tunnels[i].remotePort)
    		} else {
    			model.connectedGroup.controller.untunnel(Integer.parseInt(model.tunnels[i].localPort))
    		}
    	}
    	view.reloadTunnels()
    }
    
    void deleteTunnel(i)
    {
    	if(model.connected)
    	{
    		model.connectedGroup.controller.untunnel(Integer.parseInt(model.tunnels[i].localPort))
    	}
    	model.tunnels.remove(i)
    	view.reloadTunnels()
    }

    /** 
     * Called when the document is saved. 
     */  
    boolean save() {  
        // TODO: perform any saving tasks  
        markClean()  
        return true  
    }  
   
    /** 
     * Marks this document as 'dirty' 
     */  
    void markDirty() {  
        model.dirty = true  
        if (model.state) { model.state.dirty = true }  
        // TODO: update any other model/state properties  
        setTitle(model.name + "*")  
    }  
   
    /** 
     * Marks this document as 'clean' 
     */  
    void markClean() {  
        model.dirty = false  
        if (model.state) { model.state.dirty = false }  
        // TODO: update any other model/state properties  
        setTitle(model.name)  
    }  
   
    /** 
     * Sets this document's tab title. 
     */  
    void setTitle(title) {  
        int index = model.tabs.indexOfComponent(view.rootPanel)  
        if (index != -1) {  
            tabs.setTitleAt(index, title)  
        }  
    }  

    def  quit= { evt = null ->
    	if(close())
    	{
	    	if(model.connectedGroup!=null)
	    	{
	    		try {
	    			model.connectedGroup.controller.quit()
	    		} catch(Exception e)
		    	{
		    		logger.warn("error destroying config group",e)
		    	}
	    	}

	    	try {
	    		view.tunnels.metaClass.removeProppertyChangeListener= { 
	    			String n, c ->
	    			logger.debug('calling dodgy method');
	    			view.tunnels.removePropertyChangeListener(n, c);
	    		}
	    		destroyMVCGroup(model.mvcId)
	    	} catch (MissingMethodException mme)
	    	{
	    		logger.warn("known issue with groovy TableModelBuilder",mme)
	    	}
    		return true
    	} else {
    		logger.warn('error closing ConnectionTab group')
    		return false
    	}
    }

    /** 
     * Called when the document is closed. 
     */  
    boolean close() { 
    	
        if (model.dirty) {  
            switch (JOptionPane.showConfirmDialog(app.appFrames[0],   
                    "Save changes to '${model.savedName}'?", "Example",   
                    JOptionPane.YES_NO_CANCEL_OPTION)){  
                case JOptionPane.YES_OPTION: return save()  
                case JOptionPane.NO_OPTION: return true  
                case JOptionPane.CANCEL_OPTION: return false  
            }  
        }  
        
        return true  
    }  

    void  clear() {
		view.savedConnections.clearSelection()
		view.connectionName.text=''
		model.currentSetting.fromMap(new ConnectionSetting().toMap())
		view.user.requestFocus()
    }

}